package com.wsp.service.util;

import com.wsp.service.lock.LikeReadWriteLock;
import com.wsp.service.mapper.RecordMapper;
import com.wsp.service.service.RecordServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Package: com.wsp.service.util
 * Description： TODO
 *
 * @Author: 巫思平
 * Copyright: Copyright (c) 2020
 * Version: 1
 */
@Component
public class SnapshotSaveTask {
    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private RecordMapper recordMapper;

    private static final int MIN_SCORE_OF_REDO = 100;
    /**
     * 每天一点定时更新到数据库
     *  Seconds （秒）
     *  Minutes （分）
     *  Hours （时）
     *  Day-of-Month （天）
     *  Month （月）
     *  Day-of-Week （周）
     *  Year (年 可选字段)
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void doTask() {
        LikeReadWriteLock.writeLock.lock();
        try {
            updateNewLike(true);
            updateOlderLike(true);
        } finally {
            LikeReadWriteLock.writeLock.unlock();
        }
    }

    /**
     * 6点开始每3个小时进行一次定量检查
     */
    @Scheduled(cron = "0 0 6,9,12,15,18,21 * * ?")
    public void doCheckTask() {
        LikeReadWriteLock.writeLock.lock();
        try {
            updateNewLike(false);
            updateOlderLike(false);
        } finally {
            LikeReadWriteLock.writeLock.unlock();
        }
    }


    private void updateNewLike(boolean reflush){
        //获取需要处理的record
        Set<Object> objects;
        //定时任务，获取全部
        if(reflush) {
            objects = redisUtil.zGet(RecordServiceImpl.getNewUserRecord());
        } else {
            //定量任务获取数目100大于的全部
            objects = redisUtil.zGetBiggerScore(RecordServiceImpl.getNewUserRecord(),MIN_SCORE_OF_REDO);
        }
        if(objects==null) {
            return;
        }
        for(Object recordIdObj : objects) {
            String recordId = (String) recordIdObj;
            //获取record对应的点赞者信息
            Map<Object, Object> userLikeAndTime = redisUtil.hmget(RecordServiceImpl.getNewUserLikeList() + recordId);
            if(!reflush && userLikeAndTime.size() < 100) {
                continue;
            }
            Map<Long, Long> likeMap = new HashMap<>(userLikeAndTime.size());
            for(Map.Entry<Object, Object> entry : userLikeAndTime.entrySet()){
                String likerIdStr = entry.getKey().toString();
                Long likerId = Long.valueOf(likerIdStr);
                Long gmtCreate = (Long) entry.getValue();
                likeMap.put(likerId, gmtCreate);
            }
            if(likeMap.size() != 0) {
                //点赞者入库
                recordMapper.insertLikesBatch(Long.parseLong(recordId), likeMap);
            }
            //是否刷新
            final Integer totalLike = (Integer) redisUtil.get(RecordServiceImpl.getRecordTotalLikeNum() + recordId);
            if(totalLike != null) {
                recordMapper.updateTotalLike(Long.parseLong(recordId), totalLike);
                if (reflush) {
                    redisUtil.remove(RecordServiceImpl.getRecordTotalLikeNum() + recordId);
                    redisUtil.remove(RecordServiceImpl.getRecordUserLikeList() + recordId);
                }
            }
            //删除已经处理的点赞的redo log
            redisUtil.remove(RecordServiceImpl.getNewUserLikeList() + recordId);
            redisUtil.zRemove(RecordServiceImpl.getNewUserRecord(), recordId);
        }
    }

    /**
     * 处理新增删除点赞
     * @param reflush 刷新数据版本快照
     */
    private void updateOlderLike(boolean reflush){
        //获取需要处理的record
        Set<Object> objects;
        //定时任务，获取全部
        if(reflush) {
            objects = redisUtil.zGet(RecordServiceImpl.getDeleteUserRecord());
        } else {
            //定量任务获取数目100大于的全部
            objects = redisUtil.zGetBiggerScore(RecordServiceImpl.getDeleteUserRecord(),MIN_SCORE_OF_REDO);
        }
        if(objects==null) {
            return;
        }
        for(Object recordIdObj : objects) {
            String recordId = (String) recordIdObj;
            Map<Object, Object> olderLikeObj = redisUtil.hmget(RecordServiceImpl.getDeleteUserLikeList() + recordId);
            if(!reflush && olderLikeObj.size() < 100) {
                continue;
            }
            Set<Object> olderLike = olderLikeObj.keySet();
            if(olderLike.size() != 0) {
                recordMapper.deleteLike(Long.parseLong(recordId), olderLike);
            }
            Integer totalLike = (Integer) redisUtil.get(RecordServiceImpl.getRecordTotalLikeNum() + recordId);
            if(totalLike != null) {
                recordMapper.updateTotalLike(Long.parseLong(recordId), totalLike);
                if(reflush) {
                    redisUtil.remove(RecordServiceImpl.getRecordTotalLikeNum() + recordId);
                    redisUtil.remove(RecordServiceImpl.getRecordUserLikeList() + recordId);
                }
            }
            redisUtil.remove(RecordServiceImpl.getDeleteUserLikeList() + recordId);
            redisUtil.sRemove(RecordServiceImpl.getDeleteUserRecord(), recordId);
        }
    }
}
